﻿using RpcCentral.Common;
using RpcCentral.DAL;
using RpcCentral.Model;
using RpcHelper;
using SocketTcpClient;
using SocketTcpClient.Config;
namespace RpcCentral.Collect.Controller
{
    public class RpcServerController : DataSyncClass
    {
        private TcpClient _RemoteClient = null;
        private volatile bool _ServerIsOnline = false;

        public RpcServerController(long serverId)
        {
            ServerId = serverId;
        }
        private IRemoteServerDAL _ServerDAL
        {
            get => UnityHelper.Resolve<IRemoteServerDAL>();
        }
       
        private IServerGroupDAL _ServerGroupDAL
        {
            get => UnityHelper.Resolve<IServerGroupDAL>();
        }
        public long ServerId
        {
            get;
        }
        public RemoteServerModel Server
        {
            get;
            private set;
        }

        public string GroupTypeVal
        {
            get;
            private set;
        }
        public bool ServerIsOnline => _ServerIsOnline;

        protected override void SyncData()
        {
            this.Server = _ServerDAL.GetRemoteServer(ServerId);
            if (this.Server == null)
            {
                throw new ErrorException("rpc.server.not.find");
            }
            this.GroupTypeVal = this._ServerGroupDAL.GetTypeVal(Server.GroupId);
            if (!Server.ConIp.IsNull())
            {
                SocketConfig.AddConArg(this.Server.ConIp, this.Server.ServerPort, this.Server.PublicKey);
                this._RemoteClient = new TcpClient(this.Server.ConIp, this.Server.ServerPort);
            }
        }
        public bool ServerOnline(string conIp)
        {
            if (conIp != this.Server.ConIp)
            {
                this.Server.ConIp = conIp;
                SocketConfig.AddConArg(conIp, this.Server.ServerPort, this.Server.PublicKey);
                this._RemoteClient = new TcpClient(conIp, this.Server.ServerPort);
                this._ServerDAL.SetConIp(ServerId, conIp);
            }
            if (!this._ServerIsOnline)
            {
                if (this._ServerDAL.ServerOnline(ServerId, RpcContralConfig.ServerIndex))
                {
                    this.SendOnline();
                }
                _ServerIsOnline = true;
                Server.BindIndex = RpcContralConfig.ServerIndex;
                return true;
            }
            return false;
        }
        public bool ServerOnline(string conIp, string verNum)
        {
            if (verNum != this.Server.ApiVer)
            {
                if (verNum.IsNull())
                {
                    verNum = "0.0.0";
                }
                this._ServerDAL.SetServerApiVer(this.ServerId, verNum);
                this.Server.ApiVer = verNum;
            }
            return ServerOnline(conIp);
        }
        private void _ServerOffline()
        {
            if (_ServerIsOnline)
            {
                _ServerIsOnline = false;
                if (Server.BindIndex == RpcContralConfig.ServerIndex && _ServerDAL.ServerOffline(ServerId, RpcContralConfig.ServerIndex))
                {
                    this.SendOffline();
                }
            }
        }
        private long _errorNum = 0;

        public void ChecklsOnline()
        {
            if (_RemoteClient == null)
            {
                return;
            }
            else if (_ServerIsOnline == false)
            {
                long num = Interlocked.Increment(ref _errorNum);
                if (num == long.MaxValue)
                {
                    Interlocked.Exchange(ref _errorNum, 0);
                }
                else if (num % 10 < 5)
                {
                    return;
                }
            }
            if (!_RemoteClient.CheckIsUsable(out _))
            {
                _ServerOffline();
            }
            else if (ServerOnline(Server.ConIp))
            {
                Interlocked.Exchange(ref _errorNum, 0);
            }
        }

    }
}
